package org.codeart.pattern.prototype.api;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.*;
import java.util.List;

/**
 * 使用JavaAPI来实现原型模式
 * super.clone()方法直接从堆内存中以二进制流的方式来进行复制
 * 重新分配一个内存块,因此其效率很高,由于super.clone()方法
 * 基于内存复制,因此不会调用对象的构造函数,也就是不需要经过初始化过程.
 * 但是super.clone()方法是浅拷贝,会产生风险.
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class ConcretePrototype implements Cloneable, Serializable {

    private String desc;

    private String name;

    private List<String> hobbies;

    public ConcretePrototype(String desc) {
        this.desc = desc;
    }

    @Override
    protected ConcretePrototype clone() throws CloneNotSupportedException {
        ConcretePrototype cloneType = null;

        try {
            cloneType = (ConcretePrototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return cloneType;
    }

    public ConcretePrototype deepClone() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
                oos.writeObject(this);
            }

            try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()))) {
                return (ConcretePrototype) ois.readObject();
            } finally {
                bos.close();
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }
}
